home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-02-07 | 7.2 KB | 285 lines | [TEXT/MPS ] |
- *-------------------------------------------------------------------------------
- *
- * IMPLEMENTATION MODULE Timer
- *
- * (Timer mit Auflösung von 1.3 µs)
- *
- *
- * Version 1 / O. Maquelin / 5-Jan-89
- *
- *
- * *** Nur für Macintosh II ***
- *
- *-------------------------------------------------------------------------------
-
- MACHINE MC68020 ; nur auf Macintosh II lauffähig
- MC68881 PRECISION=X
-
- HWNonPortable EQU 1 ; für HardWareEqu
- onMac EQU 0
- onNuMac EQU 1
-
-
- INCLUDE 'HardwareEqu.a' ; VIA Adressen
- INCLUDE 'SysEqu.a' ; Variable Ticks
-
-
- EXPORT Timer: DATA
- EXPORT (InitTimer, StartTimer, StopTimer, MsValue): CODE
-
-
- * ClkPerTick = 13024
-
- ClkPerTick EQU 13024 ; Zyklen pro Tick (16.663 ms)
-
-
- * TimeRec = RECORD hi, lo: LONGCARD END
-
- TimeRec RECORD 0
- hi DS.L 1 ; High Word
- lo DS.L 1 ; Low Word
- ENDR
-
-
- * MsPerClock: LONGREAL
- * Compensation: LONGCARD
-
- Timer RECORD EXPORT,DECR ; VARs von Module Timer
- MsPerClock DC.X "1.2766E-3" ; 1.2766 µs pro Clock
- Compensation DC.L 27 ; 27 Zyklen Kompensation
- TotComp_lo DC.L 0 ; Total zu kompensieren
- TotComp_hi DC.L 0
- ENDR
-
-
- *-------------------------------------------------------------------------------
- *
- * PROCEDURE InitTimer %PASCAL (VAR t: TimeRec)
- *
- * (Initialisieren einer TimeRec Variable)
- *
- *
- * Die Felder hi und lo werden auf 0 initialisiert.
- *
- *-------------------------------------------------------------------------------
-
- InitTimer PROC EXPORT ; Von Modula-2 aus aufgerufen
-
- MOVE.L (SP)+,A0 ; Returnadresse lesen
- MOVE.L (SP)+,A1 ; Adresse von t lesen
-
- CLR.L TimeRec.hi(A1) ; hi und lo löschen
- CLR.L TimeRec.lo(A1)
-
- JMP (A0) ; Zurück zum Caller
- ENDPROC
-
-
- *-------------------------------------------------------------------------------
- *
- * PROCEDURE GetTime (VAR hi [D0], lo [D1]: LONGCARD)
- *
- * (Zeit in Maschinenzyklen bestimmen)
- *
- *
- * GetTime gibt die momentane Zeit in Maschinenzyklen (1.2766 µs) in
- * den Registern D0 und D1 zurück. Die Zeit wird anhand der globalen
- * Variable Ticks und des Zustands des VIA 2 Bausteins bestimmt.
- *
- *-------------------------------------------------------------------------------
-
- GetTime PROC ENTRY ; Nur lokal aufgerufen
-
- MOVE.L #VBase2,A1 ; Basisadresse von VIA 2 laden
-
- MOVE SR,-(SP) ; Disable Interrupts
- ORI #$0700,SR
-
- MOVE.B vT1CH(A1),D1 ; High Byte von Timer 1 lesen
- MOVE.B vBufB(A1),D0 ; Zustand von Pseudo-VBL lesen
- MOVE.B vT1C(A1),D2 ; Low Byte von Timer 1 lesen
- ROR.W #8,D2
- MOVE.B vT1CH(A1),D2 ; High Byte von Timer 1 lesen
-
- CMP.B D1,D2 ; Wenn beide High Bytes gleich
- BEQ.S @1 ; sind, ist der Wert gültig,
- ; sonst Lesevorgang wiederholen
-
- MOVE.B vBufB(A1),D0 ; Zustand von Pseudo-VBL lesen
- MOVE.B vT1C(A1),D2 ; Low Byte von Timer 1 lesen
- ROR.W #8,D2
- MOVE.B vT1CH(A1),D2 ; High Byte von Timer 1 lesen
-
- @1 ROR.W #8,D2 ; Low und High Byte vertauschen
-
- MOVEQ #7,D1 ; Erste Phase des Ticks?
- BTST.L D1,D0
- BNE.S @2
- ADD.W #ClkPerTick/2,D2 ; Nein, Zyklenzahl korrigieren
-
- @2 MOVE.L Ticks,D1 ; Ticks lesen
-
- MOVE (SP)+,SR ; Enable Interrupts
-
- CMP.W #ClkPerTick-10,D2 ; Nulldurchgang erwischt?
- BLE.S @3
- ADDQ #1,D1 ; Ja, Ticks korrigieren
-
- @3 MULU.L #ClkPerTick,D0:D1 ; Ticks mit ClkPerTick mult.
- EXT.L D2 ; und Zyklenzahl subtrahieren
- SUB.L D2,D1
- MOVEQ #0,D2 ; Extend Bit addieren
- SUBX.L D2,D0
-
- RTS ; Zurück zum Caller
- ENDPROC
-
-
- *-------------------------------------------------------------------------------
- *
- * PROCEDURE StartTimer %PASCAL (VAR t: TimeRec)
- *
- * (Timer t starten)
- *
- *
- * Die momentane Zeit in Maschinenzyklen wird vom Wert in t
- * subtrahiert. Nach StartTimer sollte der Wert von t deshalb nicht
- * gelesen werden.
- *
- *-------------------------------------------------------------------------------
-
- StartTimer PROC EXPORT ; Von Modula-2 aus aufgerufen
-
- MOVEC CACR,D0 ; Cache ausschalten
- MOVE.L D0,A0 ; Cachezustand retten
- AND.B #$FE,D0
- MOVEC D0,CACR
-
- MOVE.L Timer.Compensation,D0 ; Totale Kompensation inkrement.
- ADD.L D0,Timer.TotComp_lo
- BCC.S @1 ; Ist ein Übertrag entstanden?
- ADDQ #1,Timer.TotComp_hi ; Ja, high Word inkrementieren
-
- @1 JSR GetTime ; Momentane Zeit bestimmen
- ; -> kommt in Register D0, D1
-
- MOVE.L 4(SP),A1 ; Adresse von t lesen
-
- MOVE.L Timer.TotComp_hi,D2 ; Komp. von Zeit subtrahieren
- SUB.L Timer.TotComp_lo,D1 ; Low Word addieren
- SUBX.L D2,D0 ; High Word addieren
-
- MOVE.L TimeRec.hi(A1),D2 ; Resultat von t subtrahieren
- SUB.L D1,TimeRec.lo(A1) ; Low Word subtrahieren
- SUBX.L D0,D2 ; High Word subtrahieren...
- MOVE.L D2,TimeRec.hi(A1) ; und zurückschreiben
-
- MOVEC A0,CACR ; Cache wieder einschalten
-
- MOVE.L (SP)+,A0 ; Returnadresse lesen
- ADDQ #4,SP
- JMP (A0) ; Zurück zum Caller
- ENDPROC
-
-
- *-------------------------------------------------------------------------------
- *
- * PROCEDURE StopTimer %PASCAL (VAR t: TimeRec)
- *
- * (Timer t stoppen)
- *
- *
- * Die momentane Zeit in Maschinenzyklen wird zum Wert in t
- * addiert. Nach dem Aufruf von StartTimer und StopTimer enthält t
- * somit den Wert: <alter Wert> - <Startzeit> + <Stoppzeit>.
- *
- *-------------------------------------------------------------------------------
-
- StopTimer PROC EXPORT ; Von Modula-2 aus aufgerufen
-
- MOVEC CACR,D0 ; Cache ausschalten
- MOVE.L D0,A0 ; Cachezustand retten
- AND.B #$FE,D0
- MOVEC D0,CACR
-
- MOVE.L Timer.Compensation,D0 ; Totale Kompensation inkrement.
- ADD.L D0,Timer.TotComp_lo
- BCC.S @1 ; Ist ein Übertrag entstanden?
- ADDQ #1,Timer.TotComp_hi ; Ja, high Word inkrementieren
-
- @1 JSR GetTime ; Momentane Zeit bestimmen
- ; -> kommt in Register D0, D1
-
- MOVE.L 4(SP),A1 ; Adresse von t lesen
-
- MOVE.L Timer.TotComp_hi,D2 ; Komp. von Zeit subtrahieren
- SUB.L Timer.TotComp_lo,D1 ; Low Word addieren
- SUBX.L D2,D0 ; High Word addieren
-
- MOVE.L TimeRec.hi(A1),D2 ; Resultat zu t addieren
- ADD.L D1,TimeRec.lo(A1) ; Low Word addieren
- ADDX.L D0,D2 ; High Word addieren...
- MOVE.L D2,TimeRec.hi(A1) ; und zurückschreiben
-
- MOVEC A0,CACR ; Cache wieder einschalten
-
- MOVE.L (SP)+,A0 ; Returnadresse lesen
- ADDQ #4,SP
- JMP (A0) ; Zurück zum Caller
- ENDPROC
-
-
- *-------------------------------------------------------------------------------
- *
- * PROCEDURE MsValue %PASCAL (VAR t: TimeRec): LONGREAL
- *
- * (Wert des Timers in Millisekunden)
- *
- *
- * Diese Prozedur gibt den Wert des Timers in Millisekunden zurück:
- *
- * MsValue = (t.hi * 4294967296 + t.lo) * MsPerClock
- *
- *-------------------------------------------------------------------------------
-
- MsValue PROC EXPORT ; Von Modula-2 aus aufgerufen
-
- MOVE.L (SP)+,A0 ; Returnadresse lesen
- MOVE.L (SP)+,A1 ; Adresse von t lesen
-
- FMOVEM FP0/FP1,-(SP) ; Register FP0 und FP1 retten
-
- MOVE.L TimeRec.lo(A1),D1 ; Inhalt von t in Register laden
- MOVE.L TimeRec.hi(A1),D0
- BPL.S @1 ; Negativer Wert?
- NEG.L D1 ; Ja, Wert negieren
- NEGX.L D0
-
- @1 FMOVE.L D0,FP0 ; FP0 := t.hi
- FMOVE.L D1,FP1 ; FP1 := t.lo
- TST.L D1 ; Wert von D1 negativ?
- BPL.S @2
- FADD.X Bit32,FP1 ; Ja, Wert korrigieren
-
- @2 FMUL.X Bit32,FP0 ; FP0 := FP0 * 4294967296
- FADD FP1,FP0 ; FP0 := FP0 + FP1
- FMUL.X Timer.MsPerClock,FP0 ; FP0 := FP0 * MsPerClock
-
- TST.L TimeRec.hi(A1) ; Wert war negativ?
- BPL.S @3
- FNEG.X FP0 ; Ja, Resultat negieren
-
- @3 FMOVE.X FP0,24(SP) ; Resultat auf Stack schreiben
-
- FMOVEM (SP)+,FP0/FP1 ; Register wiederherstellen
-
- JMP (A0) ; Zurück zum Caller
-
- Bit32 DC.X "4294967296.0" ; Konstante für die Konversion
- ENDPROC
-
-
- *-------------------------------------------------------------------------------
-
- END
-